package com.starrtc.demo.imclient.client;

import com.starrtc.demo.demo.MLOC;
import com.starrtc.demo.imclient.ClientSender.ChatSender;
import com.starrtc.demo.imclient.ClientSender.LoginSender;
import com.starrtc.demo.imclient.clientCommand.console;
import com.starrtc.demo.imclient.clientCommand.ChatConsole;
import com.starrtc.demo.imclient.clientCommand.LoginConsole;
import com.starrtc.demo.imclient.clientCommand.LogoutConsole;
import com.starrtc.demo.imclient.cocurrent.FutureTaskScheduler;
import com.starrtc.demo.imclient.iMcommon.bean.UserDTO;
import com.starrtc.starrtcsdk.core.StarRtcCore;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoop;
import io.netty.util.concurrent.GenericFutureListener;

import java.util.*;
import java.util.concurrent.TimeUnit;

public class Controller {
    private StarRtcCore core = StarRtcCore.getInstance();

    private static Controller instance;

    public static Controller getInstance(){
        if(instance == null){
            instance = new Controller();
        }
        return instance;
    }

    private Controller(){
        initCommandMap();
    }

    private Map<String, console> commandMap;

    private String menuString;

    //会话类
    private ClientSession session;

    private NettyClient nettyClient;

    private Channel channel;

    private ChatSender chatSender;

    private LoginSender loginSender;


    private boolean connectFlag = false;
    private UserDTO user;

    GenericFutureListener<ChannelFuture> closeListener = new GenericFutureListener<ChannelFuture>() {
        @Override
        public void operationComplete(ChannelFuture f) throws Exception {
            channel = f.channel();

            // 创建会话
            session =
                    channel.attr(ClientSession.SESSION_KEY).get();
            session.close();

            //唤醒用户线程
            notifyCommandThread();
        }
    };


    GenericFutureListener<ChannelFuture> connectedListener = new GenericFutureListener<ChannelFuture>() {
        @Override
        public void operationComplete(ChannelFuture f) throws Exception {
            nettyClient = NettyClient.getInstance();
            final EventLoop eventLoop
                    = f.channel().eventLoop();
            if (!f.isSuccess()) {
//            log.info("连接失败!在10s之后准备尝试重连!");
                MLOC.d("!!!!!!!!!!!!!","连接失败!在10s之后准备尝试重连!");
                eventLoop.schedule(new Runnable() {
                                       @Override
                                       public void run() {
                                           nettyClient.doConnect();
                                       }
                                   },10,
                        TimeUnit.SECONDS);

                connectFlag = false;
            } else {
                //调用客户端底层登录成功方法
                core.e("AUTHKEY-FREE");

                connectFlag = true;

//            log.info("坤总  IM 服务器 连接成功!");
                channel = f.channel();

                // 创建会话
                session = new ClientSession(channel);
                session.setConnected(true);
                session.setLogin(true);
                channel.closeFuture().addListener(closeListener);

                //唤醒用户线程
                notifyCommandThread();
            }
        }
    };

    public void initCommandMap() {
        commandMap = new HashMap<>();
        commandMap.put(ChatConsole.getInstance().getKey(), ChatConsole.getInstance());
        commandMap.put(LoginConsole.getInstance().getKey(), LoginConsole.getInstance());
        commandMap.put(LogoutConsole.getInstance().getKey(), LogoutConsole.getInstance());
    }


    public void startConnectServer() {

        FutureTaskScheduler.add(new Runnable() {
            @Override
            public void run() {
                nettyClient.setConnectedListener(connectedListener);
                nettyClient.doConnect();
            }
        });
    }


    public synchronized void notifyCommandThread() {
        //唤醒，命令收集程
        this.notify();

    }

    public synchronized void waitCommandThread() {

        //休眠，命令收集线程
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    /**
     * 开始连接服务器
     */
    private void userLoginAndConnectToServer() {

        //登录
        if (isConnectFlag()) {
//            log.info("已经登录成功，不需要重复登录");
            return;
        }
//        LoginConsoleCommand command = (LoginConsoleCommand) commandMap.get(LoginConsoleCommand.KEY);

        UserDTO user = new UserDTO();
        user.setUserId(MLOC.userId);
        user.setToken("123");
        user.setDevId("1111");

//        log.info("step1：开始登录WEB GATE");
//        LoginBack webBack = WebOperator.login(command.getUserName(), command.getPassword());
//        ImNode node = webBack.getImNode();
//        log.info("step1 WEB GATE 返回的node节点是：{}", JsonUtil.pojoToJson(node));

//        log.info("step2：开始连接Netty 服务节点");
//            log.info("跳过webgate");
        nettyClient = NettyClient.getInstance();
        nettyClient.setConnectedListener(connectedListener);
//        nettyClient.setHost(node.getHost());
//        nettyClient.setPort(node.getPort());
        nettyClient.setHost("39.107.94.48");
        nettyClient.setPort(7001);
        nettyClient.doConnect();
        waitCommandThread();
//        log.info("step2：Netty 服务节点连接成功");
        MLOC.d("!!!!!!!!!!!!!","Netty 服务节点连接成功");

//        log.info("step3：开始登录Netty 服务节点");
//        while (session != null){
            loginSender = LoginSender.getInstance();
            this.user = user;
            session.setUser(user);
            loginSender.setUser(user);
            loginSender.setSession(session);
            loginSender.sendLoginMsg();
            waitCommandThread();
            connectFlag =true;
//        }
    }

    public void connectImServer() throws InterruptedException {
            //建立连接
        while (connectFlag == false) {
            //输入用户名，然后登录
            userLoginAndConnectToServer();
        }
    }
    public void sendMessage(String message){
        //处理命令
        if (null != session) {
            ChatConsole command = (ChatConsole) commandMap.get(ChatConsole.KEY);
            //传入用户输入的值
            command.exec(message);
            startOneChat(command);
        }
    }

    //发送单聊消息
    private void startOneChat(ChatConsole c) {
        chatSender = ChatSender.getInstance();
        //登录
        if (!isLogin()) {
//            log.info("还没有登录，请先登录");
            MLOC.d("!!!!!!!!!!!!!","还没有登录，请先登录");
            return;
        }
        chatSender.setSession(session);
        chatSender.setUser(user);
        chatSender.sendChatMsg(c.getToUserId(), c.getMessage());
    }




    private void startLogout(console command) {
        //登出
        if (!isLogin()) {
//            log.info("还没有登录，请先登录");
            return;
        }
        //todo 登出
    }


    public boolean isLogin() {
        if (null == session) {
//            log.info("session is null");
            MLOC.d("!!!!!!!!!!!!!","session is null");
            return false;
        }

        return session.isLogin();
    }

    public ClientSession getSession() {
        return session;
    }

    public void setSession(ClientSession session) {
        this.session = session;
    }

    public NettyClient getNettyClient() {
        return nettyClient;
    }

    public void setNettyClient(NettyClient nettyClient) {
        this.nettyClient = nettyClient;
    }

    public boolean isConnectFlag() {
        return connectFlag;
    }

    public void setConnectFlag(boolean connectFlag) {
        this.connectFlag = connectFlag;
    }

    public UserDTO getUser() {
        return user;
    }

    public void setUser(UserDTO user) {
        this.user = user;
    }

    public GenericFutureListener<ChannelFuture> getCloseListener() {
        return closeListener;
    }

    public void setCloseListener(GenericFutureListener<ChannelFuture> closeListener) {
        this.closeListener = closeListener;
    }

    public GenericFutureListener<ChannelFuture> getConnectedListener() {
        return connectedListener;
    }

    public void setConnectedListener(GenericFutureListener<ChannelFuture> connectedListener) {
        this.connectedListener = connectedListener;
    }
}
